namespace RSCore.Files;

public sealed record class TileFile(string Name) : RSFile(Name), IKeyConvertable, IExtensibleFile
{
	public readonly Dictionary<string, string> MapEntry = new();

	public string ContainerName { get; set; } = string.Empty;

	public IDictionary<string, string> ExtendedProperties => MapEntry;

	public IEnumerable<KeyValuePair<KeyData, string>> Convert()
	{
		yield return new(new(Name, EntryType.Tile, nameof(ContainerName)), ContainerName);
		foreach (var (key, value) in MapEntry)
		{
			yield return new(new KeyData(Name, EntryType.Tile, key), value);
		}
	}

	public override void Deserialize(JsonValue json)
	{
		ContainerName = json.GetText(nameof(ContainerName));
		MapEntry.Clear();
		if (json.ContainsKey(nameof(MapEntry)))
		{
			foreach (var pair in json[nameof(MapEntry)].Qo())
			{
				MapEntry.Add(pair.Key, pair.Value);
			}
		}
		return;
	}

	public override void Load(BinaryReader reader)
	{
		ContainerName = reader.ReadString();
		int count = reader.ReadInt32();
		for (int i = 0; i < count; i++)
		{
			MapEntry.Add(reader.ReadString(), reader.ReadString());
		}
	}

	public override void Read(StreamReader reader)
	{
		var properties = reader.ReadProperties();
		foreach(var (key, value) in properties)
		{
			if(key == nameof(ContainerName))
			{
				ContainerName = value;
			}
			else
			{
				MapEntry[key] = value;
			}
		}
	}

	public override void Save(BinaryWriter writer)
	{
		writer.Write(ContainerName);
		int count = MapEntry.Count;
		writer.Write(count);
		foreach (var (key, value) in MapEntry)
		{
			writer.Write(key);
			writer.Write(value);
		}
	}

	public override JsonValue Serialize()
	{
		var json = new JsonObject
		{
			{ nameof(ContainerName), ContainerName },
			{ nameof(MapEntry), new JsonObject(MapEntry.Select(pair => new KeyValuePair<string, JsonValue>(pair.Key, pair.Value))) },
		};
		return json;
	}

	public override void Write(StreamWriter writer, RSFile? annotation = null)
	{
		var orig = annotation as TileFile;
		writer.WriteProperty(ContainerName, orig?.ContainerName);
		foreach (var (key, value) in MapEntry)
		{
			if(orig != null && orig.MapEntry.TryGetValue(key, out var val))
			{
				writer.WriteProperty(value, val, key);
			}
			else
			{
				writer.WriteProperty(value, null, key);
			}
		}
	}
}